package com.sadhoc.router.routing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.sadhoc.router.routing.RouteEntry;

public class RoutingTable {
	
	// To do - I think we should use a hashMap to reduce the amount of looping? - A.Stone
	private List<RouteEntry> routingEntries = new ArrayList<RouteEntry>();
	private Object lock = new Object();
	
	public RoutingTable() {
		
	}

	public boolean addRoute (RouteEntry route) {
		synchronized (lock) {
			try {
				if(getRoute(route.getDestinationIP())==null) {
					routingEntries.add(route);
					return true;
				}
				else if(getRoute(route.getDestinationIP()).getMetric() > route.getMetric()) {
					removeRoute(route.getDestinationIP());
					routingEntries.add(route);
					System.out.println("Route to " + route.getDestinationIP() + " adjusted, lower cost through " + route.getNextHop() + " detected.\n");
					return true;
				}
				else {
					System.out.println("Route to " + route.getDestinationIP() + " through " + getRoute(route.getDestinationIP()).getNextHop() + " already exists.\n");
					return false;
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
	}
	
	public RouteEntry getRoute (String destinationIP) {
		synchronized (lock) {
			for(RouteEntry x : routingEntries) {
				if(x.getDestinationIP().equals(destinationIP))
					return x;
			}
		}
		return null;
	}
	
	public String getNextHop(String destinationIP) {
		synchronized (lock) {
			return getRoute(destinationIP).getNextHop();
		}
	}

	public boolean removeRoute (String destinationIP) {
		synchronized (lock) {
			for(RouteEntry x : routingEntries) {
				if(x.getDestinationIP().equals(destinationIP)) {
					try {
						routingEntries.remove(x);
						return true;
					}
					catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		return false;
	} 
	
	public String toString() {
		
		Collections.sort(routingEntries, new RouteEntry());
		
		String routes = "Destination\tNext Hop\tMetric\n";
		routes += "-----------\t--------\t------\n";
		
		for (RouteEntry x : routingEntries) {
				routes += x.getDestinationIP() + "\t" + x.getNextHop() + "\t" + x.getMetric() +"\n";
		}
		if (routingEntries.size() <= 0)
			routes += "No routes";
		
		return routes;
	}
	
	public List<RouteEntry> getAllEntries() {
		synchronized(lock) {
			return routingEntries;
		}
	}
	
	public void setCopyOfRoutingTable(RoutingTable table) {
		
		List<RouteEntry> newEntries = new ArrayList<RouteEntry>();
		synchronized(lock) {
			for(RouteEntry x : table.getAllEntries()) {
				newEntries.add(x.clone());
			}
			routingEntries = newEntries;
		}
		
	}
	
	public RoutingTable clone() {
		
		RoutingTable r = new RoutingTable();
		r.setCopyOfRoutingTable(this);
		return r;
		
	}
	
	public void clear() {
		synchronized(lock) {
			routingEntries.clear();
		}
	}
	
}